

#ifndef __SHAREDVALUE_H__
#define __SHAREDVALUE_H__

#include <assert.h>
#include <export.h>
#include <iobject.h>
#include <string>
#include <math/vector.h>

struct iProgramParameter;

/**
 * \addtogroup engine
 * @{
 */

/**
 * @brief Static class for getting a new free ShaderValue ID
 */


class CE_API ceSharedValueTypeProvider
{
public:
  static int GetFreeTypeId ();

};


/**
 * @brief Value to be shared between the engine and the shading system.
 */
struct iSharedValue : public iObject
{

  virtual const std::string& GetName () const = 0;

  virtual int GetTypeId () const = 0;

	virtual void Bind (iProgramParameter* parameter) = 0;

};

/**
 * @brief Abstract implementation of the iSharedValue interface providing a name.
 */
class ceSharedValueAbstract : public iSharedValue
{
private:
  std::string _name;

public:
  inline ceSharedValueAbstract (const std::string& name = "") : _name (name) { }
  inline virtual ~ceSharedValueAbstract () { _name = ""; }

  inline void SetName (const std::string& name) { _name = name; }
  inline const std::string& GetName () const { return _name; }

};

#define CE_SHARED_VALUE_TYPE                                              \
  inline int GetTypeId () const                                           \
  {                                                                       \
    static int typeId = ceSharedValueTypeProvider::GetFreeTypeId();       \
    return typeId;                                                        \
  }


/**
 * @brief Implementation of a int based shared value
 */
class CE_API ceSharedValueInt : public ceSharedValueAbstract
{
  CE_OBJECT
private:
  int					_value;

public:
  inline ceSharedValueInt (int value = 0) : ceSharedValueAbstract (), _value (value) { }
  inline ceSharedValueInt (const std::string& name, int value = 0) : ceSharedValueAbstract(name), _value (value) { }
  inline virtual ~ceSharedValueInt () { _value = 0; }

  CE_SHARED_VALUE_TYPE

  inline int GetValue () const { return _value; }
  inline void SetValue (int value) {  _value = value; }
	
  virtual void Bind (iProgramParameter* param);
};


/**
 * @brief Implementation of an unsigned int based shared value
 */
class CE_API ceSharedValueUnsignedInt : public ceSharedValueAbstract
{
  CE_OBJECT
private:
  unsigned _value;

public:
  inline ceSharedValueUnsignedInt (unsigned value = 0) : ceSharedValueAbstract (), _value (value) { }
  inline ceSharedValueUnsignedInt (const std::string& name, unsigned value = 0) : ceSharedValueAbstract(name), _value (value) { }
  inline virtual ~ceSharedValueUnsignedInt () { _value = 0; }

  CE_SHARED_VALUE_TYPE

  inline unsigned GetValue () const { return _value; }
  inline void SetValue (unsigned value) {  _value = value; }

  virtual void Bind (iProgramParameter* param);
};


/**
 * @brief Implementation of a float based shared value
 */
class CE_API ceSharedValueFloat : public ceSharedValueAbstract
{
  CE_OBJECT
private:
  float					_value;

public:
  inline ceSharedValueFloat (float value = 0.0f) : ceSharedValueAbstract (), _value (value) { }
  inline ceSharedValueFloat (const std::string& name, float value = 0.0f) : ceSharedValueAbstract(name), _value (value) { }
  inline virtual ~ceSharedValueFloat () { _value = 0; }

  CE_SHARED_VALUE_TYPE

  inline float GetValue () const { return _value; }
  inline void SetValue (float value) {  _value = value; }
	
  virtual void Bind (iProgramParameter* param);
};

/**
 * @brief Implementation of a ceVector2 based shared value
 */
class CE_API ceSharedValueVector2 : public ceSharedValueAbstract
{
  CE_OBJECT
private:
  ceVector2f					_value;

public:
  inline ceSharedValueVector2 (const ceVector2f& value) : ceSharedValueAbstract (), _value (value) { }
  inline ceSharedValueVector2 (const std::string& name, const ceVector2f& value) : ceSharedValueAbstract(name), _value (value) { }
  inline virtual ~ceSharedValueVector2 () { _value = ceVector2f (0.0f, 0.0f); }

  CE_SHARED_VALUE_TYPE

  inline const ceVector2f& GetValue () const { return _value; }
  inline void SetValue (const ceVector2f& value) {  _value = value; }
	
  virtual void Bind (iProgramParameter* param);
};


/**
 * @brief Implementation of a ceVector3 based shared value
 */
class CE_API ceSharedValueVector3 : public ceSharedValueAbstract
{
  CE_OBJECT
private:
  ceVector3f					_value;

public:
  inline ceSharedValueVector3 (const ceVector3f& value) : ceSharedValueAbstract (), _value (value) { }
  inline ceSharedValueVector3 (const std::string& name, const ceVector3f& value) : ceSharedValueAbstract(name), _value (value) { }
  inline virtual ~ceSharedValueVector3 () { _value = ceVector3f (0.0f, 0.0f, 0.0f); }

  CE_SHARED_VALUE_TYPE

  inline const ceVector3f& GetValue () const { return _value; }
  inline void SetValue (const ceVector3f& value) {  _value = value; }
	
  virtual void Bind (iProgramParameter* param);
};


/**
 * @brief Implementation of a ceVector4 based shared value
 */
class CE_API ceSharedValueVector4 : public ceSharedValueAbstract
{
  CE_OBJECT
private:
  ceVector4f					_value;

public:
  inline ceSharedValueVector4 (const ceVector4f& value) : ceSharedValueAbstract (), _value (value) { }
  inline ceSharedValueVector4 (const std::string& name, const ceVector4f& value) : ceSharedValueAbstract(name), _value (value) { }
  inline virtual ~ceSharedValueVector4 () { _value = ceVector4f (0.0f, 0.0f, 0.0f, 0.0f); }

  CE_SHARED_VALUE_TYPE

  inline const ceVector4f& GetValue () const { return _value; }
  inline void SetValue (const ceVector4f& value) {  _value = value; }
	
  virtual void Bind (iProgramParameter* param);
};


/** @} */
#endif /* ! __SHAREDVALUE_H__ */
